package com.freeheart.aop.basevalid;


import com.freeheart.aop.AopOperationUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.AspectJExpressionPointcutAdvisor;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigurationPackages;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.bind.Bindable;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.util.CollectionUtils;

import java.util.Collections;
import java.util.List;
import java.util.Set;

import static com.freeheart.aop.basevalid.BaseValidAutoConfiguration.BASE_VALID_PACKAGES;

/**
 * @author: EmperorHeart
 * @date: 2025/4/4 20:19
 * @description
 */
@AutoConfiguration
@ConditionalOnProperty(BASE_VALID_PACKAGES)
public class BaseValidAutoConfiguration {

    private final Logger logger = LoggerFactory.getLogger(BaseValidAutoConfiguration.class);

    public static final String BASE_VALID_PACKAGES = "base-valid.packages";

    public static final String DEFAULT_CONTROLLER_SUFFIX = ".controller";

    @Bean
    public BaseValidInterceptor baseValidInterceptor() {
        return new BaseValidInterceptor();
    }

    /**
     * 定义进行基础校验的Advisor/Aspect
     *
     * @param env                  Environment，用于获取{@code BASE_VALID_PACKAGES}属性值
     * @param baseValidInterceptor BaseValidInterceptor，统一检验的Advice
     * @return 基础校验的Advisor/Aspect
     */
    @Bean
    public Advisor baseValidAdvisor(ApplicationContext context, BaseValidInterceptor baseValidInterceptor) {
        Set<String> packages = deducePackages(context);
        AspectJExpressionPointcutAdvisor advisor = new AspectJExpressionPointcutAdvisor();
        advisor.setAdvice(baseValidInterceptor);
        advisor.setExpression(AopOperationUtils.packages2AspectJPointCutExpression(packages));
        return advisor;
    }

    /**
     * 推断出需要进行基础校验的包名
     *
     * @return 基础校验的包名集合
     */
    private Set<String> deducePackages(ApplicationContext context) {
        // @formatter:off
        Set<String> customPackages = Binder.get(context.getEnvironment())
                .bind(BASE_VALID_PACKAGES, Bindable.setOf(String.class))
                .orElse(Collections.emptySet());
        if (CollectionUtils.isEmpty(customPackages)) {
            List<String> autoPackages = AutoConfigurationPackages.get(context);
            if (autoPackages.size() != 1) {
                throw new IllegalArgumentException(String.format("无法推断需要基础校验的包名，请使用 %s 属性指定",BASE_VALID_PACKAGES) );
            }
            String defaultPackage = autoPackages.get(0) + DEFAULT_CONTROLLER_SUFFIX;
            logger.info("用户未指定需要基础校验的包名，默认采用:{},如需更换，请在 {} 属性中指定",defaultPackage,BASE_VALID_PACKAGES);
            return Collections.singleton(defaultPackage);
        }
        return customPackages;
    }
}
